import axios from 'axios';
import { ElMessage, ElMessageBox } from 'element-plus';
import { formatParameter, createFormData } from '@/utils/index';
import { useUserStore } from '@/stores/user'
import router from '@/router/index'
// console.log(useRouter)
// const router = useRouter;

const ERROR_MSG = '系统错误，请联系管理员';

// eslint-disable-next-line
const baseUrl = process.env.NODE_ENV === 'development' ? 'https://arrears.yyd-tech.com' : '';

// create an axios instance
const service = axios.create({
  baseURL: baseUrl,
  timeout: 60000,
  headers: {
    'Content-Type': 'application/json;charset=utf-8',
    // 'token':getStorage('token')
  },
  // withCredentials: true // 当跨域请求时，是否携带cookie。项目中使用了proxy解决跨域，不需要这个属性
});

// request interceptor
service.interceptors.request.use(
  (config) => {
    let params = config.params || config.data || {};

    if (config.headers['Content-Type'] === 'multipart/form-data') {
      params = createFormData(params);
    } else {
      params = Object.assign({}, params); // 先浅拷贝
      formatParameter(params, config.method);
    }

    if (config.method === 'get' || config.method === 'delete') {
      config.params = params;
      delete config.data;
    } else {
      config.data = params;
      delete config.params;
    }
    const userstore = useUserStore()
    config.headers.token = userstore.token
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

service.interceptors.response.use(
  (response) => {
    const res = response.data;
    const userstore = useUserStore()

    const cacheKey = getKey(response.config.url, response.config.method, response.config.data || response.config.params);
    const fail = (failRes) => {
      cache.endWithFail(cacheKey, failRes);
      return Promise.reject(failRes);
    }

    if (res.code === 4101) {
      ElMessageBox.alert(
        res.msg || ERROR_MSG,
        '登录过期',
        {
          type: 'warning',
          confirmButtonText: '重新登录',
        });

      userstore.logout()
      router.push({ path: 'login' })
      return fail(res);
    } else if (res.code === 4102) {
      ElMessage.error(res.msg || ERROR_MSG);
      userstore.logout()
      router.push({ path: 'login' })
      return fail(res);
    } else if (res.code !== 0 && res.code !== 4002) {
      ElMessage.error(res.msg || ERROR_MSG);
      return fail(res);
    }

    cache.endWithSuccess(cacheKey, res);
    return Promise.resolve(res);
  },
  (error) => {
    if (error && error.response && error.response.status >= 400) {
      if (error.response.status === 500) {
        ElMessage.error('数据异常，请刷新后重试，或联系管理员！');
      } else if (error.response.status === 429) {
        ElMessage.error('操作太频繁，请稍后重试！');
      } else {
        ElMessage.error(error.response.data.message || ERROR_MSG);
      }
    } else {
      ElMessage.error('网络开小差了');
    }

    const cacheKey = getKey(error.config.url, error.config.method, error.config.data || error.config.params);
    cache.endWithFail(cacheKey, error);
    return Promise.reject(error);
  }
);

const cache = {
  _running: {},
  _cache: {},
  start(key) {
    this._running[key] = true;
  },
  endWithSuccess(key, result) {
    this._end(key, 0, result);
  },
  endWithFail(key, result) {
    this._end(key, 1, result);
  },
  _end(key, i, result) {
    delete this._running[key];
    if (this._cache[key]) {
      for (; i < this._cache[key].length; i += 2) {
        const cb = this._cache[key][i];
        cb && cb(result)
      }
      this.clear(key)
    }
  },
  isRunning(key) {
    return !!this._running[key];
  },
  setCache(key, success, fail) {
    if (this._cache[key]) {
      this._cache[key].push(success, fail)
    } else {
      this._cache[key] = [success, fail]
    }
  },
  clear(key) {
    delete this._cache[key];
  },
  clearAll() {
    this._cache = {};
  }
}

function getKey(url, method, data) {
  method = method.toLowerCase();
  let paramsStr = '';
  if (typeof data === 'string') {
    paramsStr = data;
  } else {
    const params = Object.assign({}, data); // 先浅拷贝
    formatParameter(params, method);
    paramsStr = JSON.stringify(params);
  }
  return `${url}_${method}_${paramsStr}`;
}

export function requestCreater(url, method, options) {
  return (data, customOptions) => {
    const key = getKey(url, method, data);
    const isRequesting = cache.isRunning(key);

    if (isRequesting) {
      if (method.toLowerCase() !== 'get') return Promise.reject();

      return new Promise((resolve, reject) => {
        cache.setCache(key, resolve, reject)
      })
    }

    cache.start(key)
    const mergeOptions = Object.assign({}, options, customOptions);
    return service({
      url,
      data,
      method,
      ...mergeOptions,
    })
  };
}

export function serverCreater(url, options) {
  return {
    get: requestCreater(url, 'get', options),
    post: requestCreater(url, 'post', options),
    put: requestCreater(url, 'put', options),
    delete: requestCreater(url, 'delete', options),
  }
}